#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const int Maxn = 10010;
const double Eps = 1e-12;
struct point {
	double x, y;
	point() {}
	point( double _x, double _y ) : x( _x ), y( _y ) {}
	inline point operator + ( const point Other ) const {
		return point( x + Other.x, y + Other.y );
	}
	inline point operator - ( const point Other ) const {
		return point( x - Other.x, y - Other.y );
	}
	inline double operator * ( const point Other ) const {
		return x * Other.y - Other.x * y;
	}
	inline point operator * ( const double Other ) const {
		return point( x * Other, y * Other );
	}
	inline double Mod() const { return sqrt( x * x + y * y ); }
};
int N, M, Size;
point A[ Maxn ], B[ Maxn ], Base, Stack[ Maxn ];

int Cmp( double x, double y ) {
	if( fabs( x - y ) <= Eps ) return 0;
	if( x - y > Eps ) return 1;
	return -1;
}
bool Cmp1( point X, point Y ) {
	return Cmp( ( X - Base ) * ( Y - Base ), 0.0 ) == 1 || 
		( Cmp( ( X - Base ) * ( Y - Base ), 0.0 ) == 0 && Cmp( ( X - Base ).Mod(), ( Y - Base ).Mod() ) == -1 );
}
void Graham( point *A, int &N ) {
	for( int i = 2; i <= N; ++i ) 
		if( Cmp( A[ i ].y, A[ 1 ].y ) == -1 || 
				( Cmp( A[ i ].y, A[ 1 ].y ) == 0 && Cmp( A[ i ].x, A[ 1 ].x ) == -1 ) )
			swap( A[ i ], A[ 1 ] );
	Base = A[ 1 ]; sort( A + 2, A + N + 1, Cmp1 );
	Size = 1; Stack[ 1 ] = A[ 1 ];
	for( int i = 2; i <= N; ++i ) {
		for( ; Size > 1 && Cmp( ( A[ i ] - Stack[ Size - 1 ] ) * ( Stack[ Size ] - Stack[ Size - 1 ] ), 0.0 ) >= 0; --Size );
		Stack[ ++Size ] = A[ i ];
	}
	N = Size; for( int i = 1; i <= N; ++i ) A[ i ] = Stack[ i ];
	return;
}
inline int Pre( int N, int x ) { return ( x - 1 < 1 ) ? N : x - 1; }
inline int Suc( int N, int x ) { return ( x + 1 > N ) ? 1 : x + 1; }
inline double GetDis( point A, point B, point C ) {
	point D = C + point( -( B - A ).y, ( B - A ).x );
	double K = ( D - A ) * ( C - A ) / ( ( C - B ) * ( D - B ) );
	if( Cmp( K, 0.0 ) <= 0 ) return min( ( C - A ).Mod(), ( C - B ).Mod() );
	point O = A * ( 1.0 / ( K + 1.0 ) ) + B * ( K / ( K + 1.0 ) );
	return ( C - O ).Mod();
}
double Dis( point *A, int N, point *B, int M ) {
	int i1 = 1, i2; 
	for( i2 = 1; i2 <= M; ++i2 )
		if( Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ i2 ] - B[ Pre( M, i2 ) ] ), 0.0 ) == 1 &&
				Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ Suc( M, i2 ) ] - B[ i2 ] ), 0.0 ) <= 0 )
			break;
	double Ans = GetDis( A[ Suc( N, i1 ) ], A[ i1 ], B[ i2 ] );
	if( Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ Suc( M, i2 ) ] - B[ i2 ] ), 0.0 ) == 0 ) {
		i2 = Suc( M, i2 );
		Ans = min( Ans, GetDis( A[ Suc( N, i1 ) ], A[ i1 ], B[ i2 ] ) );
	}
	for( ++i1; i1 <= N; ++i1 ) {
		for( ; Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ i2 ] - B[ Pre( M, i2 ) ] ), 0.0 ) <= 0 ||
				Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ Suc( M, i2 ) ] - B[ i2 ] ), 0.0 ) == 1; i2 = Suc( M, i2 ) );
		Ans = min( Ans, GetDis( A[ Suc( N, i1 ) ], A[ i1 ], B[ i2 ] ) );
		if( Cmp( ( A[ Suc( N, i1 ) ] - A[ i1 ] ) * ( B[ Suc( M, i2 ) ] - B[ i2 ] ), 0.0 ) == 0 ) {
			i2 = Suc( M, i2 );
			Ans = min( Ans, GetDis( A[ Suc( N, i1 ) ], A[ i1 ], B[ i2 ] ) );
		}
	}
	return Ans;
}
int main() {
	scanf( "%d%d", &N, &M );
	for( ; N != 0 || M != 0; scanf( "%d%d", &N, &M ) ) {
		for( int i = 1; i <= N; ++i ) scanf( "%lf%lf", &A[ i ].x, &A[ i ].y );
		for( int i = 1; i <= M; ++i ) scanf( "%lf%lf", &B[ i ].x, &B[ i ].y );
		Graham( A, N ); Graham( B, M );
		printf( "%.6lf\n", min( Dis( A, N, B, M ), Dis( B, M, A, N ) ) );
	}
	return 0;
}

